Data Profiling

Contexto

El siguiente proyecto tiene como finalidad hacer un análisis exploratorio sobre los datos históricos de los meses de enero hasta julio del año 2018 proporcionados por la página de ecobici; en la misma liga se puede econtrar lo necesario para accesar al API proporcionado por este servicio. La documentación sobre la API se encuentra en la siguiente liga

Ecobici es un servicio de bicicletas públicas de la Ciudad de México dirigido a los habitantes de la capital, de sus alrededores y a los turistas.

El funcionamiento de este servicio permite a los usuarios registrados tomar una bicicleta de cualquier cicloestación y devolverla en la más cercana a su destino en trayectos ilimitados de 45 minutos.

La forma para acceder a este servicio es mediante un suscripción anual, semanal, de cada tres días o diaria

Este servicio está disponible en un horario de 5:00 hrs hasta 00:30 hrs todos los días del año, el cuál inicio en el año 2010, febrero con 84 cicloestaciones y mil 200 bicicletas.

Actualmente Ecobici cuenta con más de 170 mil usuarios registrados y el servicio está disponible en 55 colonias de la Ciudad de México, en un área de 38 kilómetros cuadrados.

El API de ecobicise enfoca en datos actuales y el objetivo es sobre los datos históricos, para su obtención no es necesario utilizar la API.

Los datos fueron descargados y almacenados en una BD llamada ECOBICI; el dump para exportar esta BD se encuentra en los archivos suministrados en este proyecto en la carpeta data

La BD ECOBICI contiene 7 tablas, una por cada mes, es decir, una por cada archivo descargado directamente de la página de ecobici; cada tabla contiene los siguientes campos:

  • genero_usuario: Genero del usuario que utilizó el servicio ecobici.
  • edad_usuario: Edad del usuario que utilizó el servicio ecobici.
  • id_bici: Identificador de la bicicleta utilizada.
  • ciclo_estacion_retiro: Identificador de la estación donde se retiró la bicicleta.
  • re_date: Fecha de retiro de la bicicleta de la última estación registada para su utilzación.
  • re_time: Hora de retiro de la bicicleta de la última estación registrada para su utilización.
  • ciclo_estacion_arribo: Identificador de la estación donde se deposita la bicicleta.
  • ciclo_estacion_arribo: Fecha de llegada de la bicicleta a la estación de arrivo.
  • arr_time: Hora de llegada de la bicicleta a la estación de arrivo.

El siguiente código sirve para acceder a una base de datos de MySQL, sin embargo lo que yo utilicé fue directamente de archivos Excel y construcción de Data Frames ¿Por qué? Porque utilizo la computadora del trabajo que tiene algunas restricciones para copiar archivos directamente de Excel en base de datos.

library(readr)
library(ggplot2)
library(stringr)
library(dplyr)
library(knitr) #para generar una tabla cool en el reporte
library(tidyr) #para manipulacion de datos
library(lubridate)
library(ggmap)
library(plotly)
library(tidyverse)
library(RMySQL)
library(pool)
library(DBI)

Si me hubiera conectado a una base de datos:

Se procederá a la conexión y extracción de datos desde la BD

"[db.host <- 'localhost'
db.user <- 'root'
db.port <- 3306
db.password <- 'Calderon260'

## DB Connection
db_connect <- function(db.name) {
  db <- dbPool(
    drv = RMySQL::MySQL(),
    dbname = db.name,
    host = db.host,
    user = db.user,
    password = db.password,
    port = as.numeric(db.port)
  )
  
  return(db)
}]"
## [1] "[db.host <- 'localhost'\ndb.user <- 'root'\ndb.port <- 3306\ndb.password <- 'Calderon260'\n\n## DB Connection\ndb_connect <- function(db.name) {\n  db <- dbPool(\n    drv = RMySQL::MySQL(),\n    dbname = db.name,\n    host = db.host,\n    user = db.user,\n    password = db.password,\n    port = as.numeric(db.port)\n  )\n  \n  return(db)\n}]"

Nos interesa hacer un análisis sobre todos los datos por lo que, para evitar seleccionar todo por partes de cada tabla, se extraeran todos los datos de cada tabla.

"[
January <- tbl(db_connect('ECOBICI'), 'Enero') %>% collect()
February <- tbl(db_connect('ECOBICI'), Febrero') %>% collect()
March <- tbl(db_connect('ECOBICI'), Marzo) %>% collect()
April <- tbl(db_connect('ECOBICI'), Abril) %>% collect()
May <- tbl(db_connect('ECOBICI'), 'Mayo') %>% collect()
June <- tbl(db_connect('ECOBICI'), 'Junio') %>% collect()
July <- tbl(db_connect('ECOBICI'), 'Julio') %>% collect()
]"
## [1] "[\nJanuary <- tbl(db_connect('ECOBICI'), 'Enero') %>% collect()\nFebruary <- tbl(db_connect('ECOBICI'), Febrero') %>% collect()\nMarch <- tbl(db_connect('ECOBICI'), Marzo) %>% collect()\nApril <- tbl(db_connect('ECOBICI'), Abril) %>% collect()\nMay <- tbl(db_connect('ECOBICI'), 'Mayo') %>% collect()\nJune <- tbl(db_connect('ECOBICI'), 'Junio') %>% collect()\nJuly <- tbl(db_connect('ECOBICI'), 'Julio') %>% collect()\n]"

Como yo leí la información directamente de los archivos de excel :

January <- read_csv("data/2018-01.csv",col_names = T, na = c(""," ", "NA", "?"))
February <- read_csv("data/2018-02.csv",col_names = T, na = c(""," ", "NA", "?"))
March <- read_csv("data/2018-03.csv",col_names = T, na = c(""," ", "NA", "?"))
April <- read_csv("data/2018-04.csv",col_names = T, na = c(""," ", "NA", "?"))
May <- read_csv("data/2018-05.csv",col_names = T, na = c(""," ", "NA", "?"))
June <- read_csv("data/2018-06.csv",col_names = T, na = c(""," ", "NA", "?"))
July <- read_csv("data/2018-07.csv",col_names = T, na = c(""," ", "NA", "?"))

names(January) <- tolower(names(January))
names(February) <- tolower(names(February))
names(March) <- tolower(names(March))
names(April) <- tolower(names(April))
names(May) <- tolower(names(May))
names(June) <- tolower(names(June))
names(July) <- tolower(names(July))

Ahora, un poco de limpieza

January

Con la siguiente función se modificará el tipo de dato en genero_usuario y se colapsará los datos de tiempo y fecha en un sólo dato para los tiempos de arrivo y los tiempos de retiro registrados

gender_arr_fix <- function(data){
  new_data <- data %>% 
    mutate(genero_usuario = factor(genero_usuario, levels = c("M", "F")), 
      hora_arribo = str_replace(hora_arribo, "(\\w+:\\w+:\\w+)\\r", "\\1"),
      fecha_retiro = dmy(fecha_retiro),
      hora_retiro = hms(hora_retiro), 
      fecha_arribo = dmy(fecha_arribo), 
      hora_arribo = hms(hora_arribo)
    ) %>% 
    mutate(re_datetime = make_datetime(year(fecha_retiro),
                                       month(fecha_retiro), 
                                       day(fecha_retiro),
                                       hour(hora_retiro), 
                                       minute(hora_retiro),
                                       second(hora_retiro)), 
           arr_datetime = make_datetime(year(fecha_arribo),
                                       month(fecha_arribo), 
                                       day(fecha_arribo),
                                       hour(hora_arribo), 
                                       minute(hora_arribo),
                                       second(hora_arribo))) %>% 
    select(-c(fecha_retiro, hora_retiro, fecha_arribo, hora_arribo))
  return(new_data)
}

Modificamos la tabla con la función previamente creada

January <- gender_arr_fix(January)
February <- gender_arr_fix(February)
March <- gender_arr_fix(March)
April <- gender_arr_fix(April)
May <- gender_arr_fix(May)
June <- gender_arr_fix(June)
July <- gender_arr_fix(July)
July

Para realizar un perfilamiento de datos se hace uso del módulo `DataProfiling el cual se encuentra en los documentos de este proyecto.

source("DataProfiling.R")

Ahora, se hará el data profiling por cada mes

Hay que observar que edad_usuario, id_bici, ciclo_estacion_retiro, ciclo_estacion_arribo son identificadores, por lo que, aunque sean de tipo numérico, no proporcionan alguna información cuantitativa relevante, por lo que solo se observarán características sobre los datos que no incluya resumenes numericos.

Primero un conteo de datos y después un resumen por cada mes.

Enero

Jan_fac <- January %>% select(-c(re_datetime, arr_datetime))
Jan_date <- January %>% select(c(re_datetime, arr_datetime))

Se construye una tabla con especificaciones de formato, que los números muy grandes los separe con “,” y que no utilice notación científica

Jan_factor <- Jan_fac %>% profiling("categorical")
kable(Jan_factor, format.args = list(big.mark=",", scientific=F))
uniques nan mode
genero_usuario 2 0 M
edad_usuario 67 0 28
bici 4,897 1 7376
ciclo_estacion_retiro 432 0 271
ciclo_estacion_arribo 435 0 1

Para los datos de tiempo sólo se verifica si existen valores nulos y el conteo de los valores únicos.

Jan_datetime <- Jan_date %>% profiling("other")
kable(Jan_datetime, format.args = list(big.mark=",", scientific=F))
uniques nan
re_datetime 545,217 0
arr_datetime 545,660 0
Y no hay valore s nulos

Hallazgos de Enero

  • La mayoría de los usuarios son de género masculino.
  • La mayoría de los usuarios tienen 28 años
  • La bicicleta con id 7376 fue la más usada
  • La estación más concurrida para tomar una bicicleta fue la 271
  • La estación más concurrida para dejar una bicicleta fue la 1

Febrero

Feb_fac <- February %>% select(-c(re_datetime, arr_datetime))
Feb_date <- February %>% select(c(re_datetime, arr_datetime))

Feb_factor <- Feb_fac %>% profiling("categorical")
kable(Feb_factor, format.args = list(big.mark=",", scientific=F))
uniques nan mode
genero_usuario 2 0 M
edad_usuario 73 0 28
bici 5,058 44 2019
ciclo_estacion_retiro 476 0 271
ciclo_estacion_arribo 476 0 43
Feb_datetime <- Feb_date %>% profiling("other")
kable(Feb_datetime, format.args = list(big.mark=",", scientific=F))
uniques nan
re_datetime 541,252 0
arr_datetime 541,095 0

Hallazgos de Febrero

  • La mayoría de los usuarios son de género masculino.
  • La mayoría de los usuarios tienen 28 años
  • La bicicleta con id 2019 fue la más usada
  • La estación más concurrida para tomar una bicicleta fue la 271
  • La estación más concurrida para dejar una bicicleta fue la 43

Marzo

Mar_fac <- March %>% select(-c(re_datetime, arr_datetime))
Mar_date <- March %>% select(c(re_datetime, arr_datetime))

Mar_factor <- Mar_fac %>% profiling("categorical")
kable(Mar_factor, format.args = list(big.mark=",", scientific=F))
uniques nan mode
genero_usuario 2 0 M
edad_usuario 72 0 28
bici 4,931 122 2698
ciclo_estacion_retiro 476 0 271
ciclo_estacion_arribo 478 0 27
Mar_datetime <- Mar_date %>% profiling("other")
kable(Mar_datetime, format.args = list(big.mark=",", scientific=F))
uniques nan
re_datetime 580,412 0
arr_datetime 579,596 0

Hallazgos de Marzo

  • La mayoría de los usuarios son de género masculino.
  • La mayoría de los usuarios tienen 28 años
  • La bicicleta con id 2698 fue la más usada
  • La estación más concurrida para tomar una bicicleta fue la 271
  • La estación más concurrida para dejar una bicicleta fue la 27

Abril

A_fac <- April %>% select(-c(re_datetime, arr_datetime))
A_date <- April %>% select(c(re_datetime, arr_datetime))

A_factor <- A_fac %>% profiling("categorical")
kable(A_factor, format.args = list(big.mark=",", scientific=F))
uniques nan mode
genero_usuario 2 0 M
edad_usuario 71 0 28
bici 4,889 132 11065
ciclo_estacion_retiro 478 0 27
ciclo_estacion_arribo 478 0 27
A_datetime <- A_date %>% profiling("other")
kable(A_datetime, format.args = list(big.mark=",", scientific=F))
uniques nan
re_datetime 589,901 0
arr_datetime 589,669 0

Hallazgos de Abril

  • La mayoría de los usuarios son de género masculino.
  • La mayoría de los usuarios tienen 28 años
  • La bicicleta con id 11065 fue la más usada
  • La estación más concurrida para tomar una bicicleta fue la 27
  • La estación más concurrida para dejar una bicicleta fue la 27

Mayo

May_fac <- May %>% select(-c(re_datetime, arr_datetime))
May_date <- May %>% select(c(re_datetime, arr_datetime))

May_factor <- May_fac %>% profiling("categorical")
kable(May_factor, format.args = list(big.mark=",", scientific=F))
uniques nan mode
genero_usuario 2 0 M
edad_usuario 72 0 28
bici 4,982 0 15259
ciclo_estacion_retiro 480 0 271
ciclo_estacion_arribo 480 0 27
May_datetime <- May_date %>% profiling("other")
kable(May_datetime, format.args = list(big.mark=",", scientific=F))
uniques nan
re_datetime 618,668 0
arr_datetime 618,486 0

Hallazgos de Mayo

  • La mayoría de los usuarios son de género masculino.
  • La mayoría de los usuarios tienen 28 años
  • La bicicleta con id 15259 fue la más usada
  • La estación más concurrida para tomar una bicicleta fue la 271
  • La estación más concurrida para dejar una bicicleta fue la 27

  • Junio

Jun_fac <- June %>% select(-c(re_datetime, arr_datetime))
Jun_date <- June %>% select(c(re_datetime, arr_datetime))

Jun_factor <- Jun_fac %>% profiling("categorical")
kable(Jun_factor, format.args = list(big.mark=",", scientific=F))
uniques nan mode
genero_usuario 2 0 M
edad_usuario 71 0 28
bici 4,980 0 2789
ciclo_estacion_retiro 479 0 271
ciclo_estacion_arribo 479 0 27
Jun_datetime <- Jun_date %>% profiling("other")
kable(Jun_datetime, format.args = list(big.mark=",", scientific=F))
uniques nan
re_datetime 545,135 0
arr_datetime 545,241 0

Hallazgos de Junio

  • La mayoría de los usuarios son de género masculino.
  • La mayoría de los usuarios tienen 28 años
  • La bicicleta con id 2789 fue la más usada
  • La estación más concurrida para tomar una bicicleta fue la 271
  • La estación más concurrida para dejar una bicicleta fue la 27

  • Julio

July_fac <- July %>% select(-c(re_datetime, arr_datetime))
July_date <- July %>% select(c(re_datetime, arr_datetime))

July_factor <- July_fac %>% profiling("categorical")
kable(July_factor, format.args = list(big.mark=",", scientific=F))
uniques nan mode
genero_usuario 2 0 M
edad_usuario 70 0 28
bici 4,929 0 9581
ciclo_estacion_retiro 480 0 27
ciclo_estacion_arribo 480 0 27
July_datetime <- July_date %>% profiling("other")
kable(July_datetime, format.args = list(big.mark=",", scientific=F))
uniques nan
re_datetime 568,438 0
arr_datetime 569,168 0

Hallazgos de Enero

  • La mayoría de los usuarios son de género masculino.
  • La mayoría de los usuarios tienen 28 años
  • La bicicleta con id 9581 fue la más usada
  • La estación más concurrida para tomar una bicicleta fue la 27
  • La estación más concurrida para dejar una bicicleta fue la 27

Vease que la estación número 271 es la que tiene un mayor número de registros donde los usuarios tomaron una biclceta en los meses de :

  • Enero, Febrero, Marzo, Mayo y Junio.

Por otro lado, la estación 27 en los meses de Abril y Julio es donde se obtienen la mayor cantidad de registros donde los usuarios tomaron una bicicleta. Esta estación es tienen la mayoría donde los usuarios depositaron una bicicleta en los meses de :

  • Marzo, Abril, Mayo, Junio y Julio.

Ahora, surgen varias preguntas o issues sobre los datos.

EDA

A continuación se presenta un análisis exploratorio.

Ubicaciones más recurrentes

¿Dónde se ubican las estaciones más 27 y 271, así como la 1 y 43?

Un mapa de todas las cicloestaciones se encuentra en la página oficial de ecobici, aunque en esta liga se encuentra el archivo correspondiente.

La ubicación de cada una de las 480 estaciones se encuentra en la siguiente página

O bien se puede conseguir desde la API, donde se necesita un access token, obtenido de las credenciales propias de cada usuario, este access token tiene tiempo de vida de una hora. (poner en navegador https://pubsbapi.smartbike.com/oauth/v2/token?client_id=585_5oct79smo5s8kk0ksggkg0sokkkwwk00o0ssw4ww840gg04owc&clien t_secret=il6ccw6rdtkwo00cwoc44w4c8wgc4084g4gosowws004k888g&grant_type=client_credentials)

Interacción con API

#install.packages(httr)
# library(httr)
# ecobici_api <- function(path) {
#   url <- modify_url("https://pubsbapi.smartbike.com", path = path)
#   
#   resp <- GET(url)
#   if (http_type(resp) != "application/json") {
#     stop("API did not return json", call. = FALSE)
#   }
#   
#   parsed <- jsonlite::fromJSON(content(resp, "text"), simplifyVector = FALSE)
#   
#   if (http_error(resp)) {
#     stop(
#       sprintf(
#         "Ecobici API request failed [%s]\n%s\n<%s>", 
#         status_code(resp),
#         parsed$message,
#         parsed$documentation_url
#       ),
#       call. = FALSE
#     )
#   }
#   
#   structure(
#     list(
#       content = parsed,
#       path = path,
#       response = resp
#     ),
#     class = "ecobici_api"
#   )
# }
# 
# print.ecobici_api <- function(x, ...) {
#   cat("<Ecobici ", x$path, ">\n", sep = "")
#   str(x$content)
#   invisible(x)
# }
# 
# ecobici_api("/api/v1/stations.json?access_token=OTcyMmJkYjUxYWM4MzQzMjQ0YTU3Njk3MjNkYzkyNWJmYzIwNjVkZTcyYTJlMjM3Yzg3NmQ1YTUwZGY2MGFmYg")

Las anteriores estaciones son las siguientes:

  • 27 REFORMA-HAVRE
# first_station <- geocode('Paseo de la Reforma y Havre, Juárez, 06600 Ciudad de México, Ciudad de México, México', 
#                   source = "google")
# map_first_station <- get_map(location = as.numeric(first_station),
#                       color = "color",
#                       maptype = "roadmap",
#                       scale = 2,
#                       zoom = 16)
# ggmap(map_first_station) + geom_point(aes(x = lon, y = lat),
#                                data = first_station , colour = 'green',
#                                shape = 20, size = 10, fill= "green")
  • 271 AV. CENTRAL-J. MENESES
# second_station <- geocode('Jesús García 271, Buenavista, 06350 Ciudad de México, CDMX, México', 
#                   source = "google")
# 
# map_second_station <- get_map(location = as.numeric(second_station),
#                       color = "color",
#                       maptype = "roadmap",
#                       scale = 2,
#                       zoom = 16)
# 
# ggmap(map_second_station) + geom_point(aes(x = lon, y = lat),
#                                data = second_station , colour = 'green',
#                                shape = 20, size = 10, fill= "green")
  • 1 RIO SENA-RIO BALSAS
# third_station <- geocode('Rio Sena y Rio balsas, Ciudad de México, CDMX, México', 
#                   source = "google")
# 
# map_third_station <- get_map(location = as.numeric(third_station),
#                       color = "color",
#                       maptype = "roadmap",
#                       scale = 2,
#                       zoom = 16)
# 
# ggmap(map_third_station) + geom_point(aes(x = lon, y = lat),
#                                data = third_station , colour = 'green',
#                                shape = 20, size = 10, fill= "green")
  • 1 RIO SENA-RIO BALSAS
# fourth_station <- geocode('Juarez y Revillagigedo, Ciudad de México, CDMX, México', 
#                   source = "google")
# 
# map_fourth_station <- get_map(location = as.numeric(fourth_station),
#                       color = "color",
#                       maptype = "roadmap",
#                       scale = 2,
#                       zoom = 16)
# 
# ggmap(map_fourth_station) + geom_point(aes(x = lon, y = lat),
#                                data = fourth_station , colour = 'green',
#                                shape = 20, size = 10, fill= "green")

En resumen

  • La estación con más concurrencia fue la que estaba ubicada sobre reforma, cerca de Reforma 222, que es una plaza comercial y centro de trabajo.

  • Dos estaciones se ubican cerca del metro Buenavista, donde es un punto de conexión entre mucha gente que viene del Estado de México y otras partes de la Ciudad de México para viajar a las zonas donde se encuentra la mayor densidad de empleos.

  • Por último la estación 43, que en el momento de escribir esto, se encuentra fuera de operación, sin embargo es de mucha concurrencia al tener cercanía con Reforma y el centro.

Para tener todos los datos recabados en los meses de enero hasta julio del 2018, se junta todo para así obtener el tiempo promedio que los usuarios utilizan el servicio de ecobici de todas las estaciones con usabilidad registrada.

historicos_ecobici <- rbind(January, February, March, April, May, June, July)

Ahora se agrega el tiempo que un usuario utilizo alguna bicicleta:

historicos_ecobici <- historicos_ecobici %>% 
  mutate(duracion = as.duration(arr_datetime-re_datetime))
historicos_ecobici

Si se ordenan estos datos por el tiempo de uso por usuario:

historicos_ecobici <- historicos_ecobici %>% arrange(duracion)

Hay registros donde los usuarios tardaron 0 y hasta 1 segundo en dejar una bicicleta en estaciones distintas, esto es posiblemente debido a dos cosas principalmente:

1.- Si tu ecobici no la encuentras en buen funcionamiento, tienes hasta 2 minutos para regresarla. 2.- Hay veces en que tomas la ecobici y se te cae por descuido, así que debes solicitar una de nuevo.

historicos_ecobici %>% arrange(desc(duracion)) %>% filter(ciclo_estacion_retiro != ciclo_estacion_arribo)

Hay registros donde los usuarios tardaron hasta 1.53 años en devolver una bicicleta, también semanas y hasta días.

Para evitar tomar datos donde los usuarios tuvieron algun error, o devolvieron la ecobici, o tardaron más de lo reglamentado, se tomaron aquellos datos con una duración a 30 segundos de una estación a otra y aquellos que cumplan con el reglamento establecido de ecobici en cuanto a la duración de 45 minutos.

new_historicos_ecobici <- historicos_ecobici %>% filter(duracion <= dminutes(45))
new_historicos_ecobici <- new_historicos_ecobici %>% filter(dseconds(30) <= duracion)
new_historicos_ecobici %>% arrange(duracion)
new_historicos_ecobici <- new_historicos_ecobici %>% arrange(desc(duracion))
new_historicos_ecobici
promedio_tiempo_uso <- mean(new_historicos_ecobici$duracion)
promedio_tiempo_uso <- minute(seconds_to_period(round(promedio_tiempo_uso)))

print(str_c("El promedio de tiempo de uso de una ecobici dentro del tiempo reglamentario, en la Ciudad de México es de: ", promedio_tiempo_uso, " minutos"))
## [1] "El promedio de tiempo de uso de una ecobici dentro del tiempo reglamentario, en la Ciudad de México es de: 13 minutos"

Con esta nueva limpieza, obtenemos aquellos registros entre las dos estaciones de estudio (271, 27, 1 y 43)

new_historicos_ecobici %>% 
  filter(ciclo_estacion_retiro %in% c(1, 43, 27, 271) | ciclo_estacion_retiro %in% c(1, 43, 27, 271)) 

Gráficos sobre edad y uso del servicio Ecobici

Continuando con algunos otros datos, la siguiente gráfica muestra la proporción sobre el uso del servicio ecobici por edades registradas.

Por convención, se omitirán aquellos datos en el cual la edad es mayor a 85 años

new_historicos_ecobici %>% 
  filter(edad_usuario < 85) %>% 
  group_by(edad_usuario) %>% 
  dplyr::summarise(count = n()) %>% 
  mutate(proportion = count/sum(count)) %>% 
  ggplot(aes(x = edad_usuario, y = proportion, fill = proportion)) +
  geom_bar(stat = "identity") +
  ggtitle("Proporción de uso del servicio sobre la edad de los usuarios ")

¿Cuáles son las horas más y menos comunes de servicio?

Esto servirá para saber cuando se requiere mayor demanda de servicio y mayor disponibilidad de bicicletas. Se utiliza el parámetro re_datetime porque es la hora en la cual los usuarios comienzan a usar una bicicleta, que no debería variar mucho a lo largo del día coparado con arr_datetime, porque el tiempo de uso con las nuevas tablas es de menos de 45 minutos.

por_hora_del_dia <- new_historicos_ecobici %>% 
    mutate(hora = hour(re_datetime)) %>% 
    group_by(hora)  %>% 
    dplyr::summarise(conteo = n()) %>% 
  ggplot(aes(x = hora, y = conteo, fill = conteo)) +
  geom_bar(stat = "identity")+
  ggtitle("Cantidad de usuarios activos por hora que toman una ecobici")
ggplotly(por_hora_del_dia)
por_hora_del_dia <- new_historicos_ecobici %>% 
    mutate(hora = hour(arr_datetime)) %>% 
    group_by(hora)  %>% 
    dplyr::summarise(conteo = n()) %>% 
  ggplot(aes(x = hora, y = conteo, fill = conteo)) +
  geom_bar(stat = "identity")+
  ggtitle("Cantidad de usuarios activos por hora que dejan una ecobici")
ggplotly(por_hora_del_dia)

Para tener los datos de cuales son las 10 horas donde hay mayor demanda de cobici se cuentan los usuarios por hora:

new_historicos_ecobici %>% 
  mutate(hora = hour(re_datetime)) %>% 
  group_by(hora)  %>% 
  dplyr::summarise(conteo = n()) %>%
  arrange(desc(conteo)) %>% 
  head(10)
## # A tibble: 10 x 2
##     hora conteo
##    <int>  <int>
##  1    18 483166
##  2     8 478318
##  3    19 391346
##  4     9 370395
##  5    17 353746
##  6    14 348941
##  7    15 347330
##  8    16 287176
##  9    13 286461
## 10     7 261877

¡Bingo!

Es curioso que estas horas coincidan con la hora habitual para entrar y salir de trabajar en la Ciudad de México, lo que tiene sentido, porque mucha gente va al trabajo en estos vehículos.

Para finalizar, algunas preguntas sobre el genero de los usuarios.

Falta un análisis de realizar y es para saber qué días de la semana tienen mayor demanda de bicicletas, por la cantidad de usuarios que toman alguna

por_dia_semana <- new_historicos_ecobici %>% 
  mutate(dia_semana = format(as.Date(re_datetime),"%A")) %>% 
  group_by(dia_semana)  %>% 
  dplyr::summarise(conteo = n()) %>%
  arrange(desc(conteo))
por_dia_semana
## # A tibble: 7 x 2
##   dia_semana conteo
##   <chr>       <int>
## 1 Tuesday    900937
## 2 Wednesday  895546
## 3 Thursday   865172
## 4 Monday     822882
## 5 Friday     815889
## 6 Saturday   374238
## 7 Sunday     323518
dias_sem <- ggplot(por_dia_semana, aes(x=dia_semana, y=conteo, fill= dia_semana)) +
  geom_bar(stat = "identity")+
  ggtitle("Cantidad de usuarios por día de la semana")
ggplotly(dias_sem)

Es muy claro que la actividad disminuye en fines de semana a menos de la mitad habitual y el día más concurrido es el martes.

gender <- ggplot(new_historicos_ecobici, aes(genero_usuario, fill = genero_usuario)) +
  geom_bar() +
  scale_x_discrete(drop = FALSE)+
  ggtitle("Cantidad de usuarios por genero en los registros")
ggplotly(gender)

Es notable la diferencia entre la cantidad de hombres que utilizan este servicio contra el genero femenino.

Búsqueda de Publicaciones por hashtag #ecobici en Twitter

Búsqueda de twits relacionados con ecobici

# creamos una llave en https://dev.twitter.com/apps
consumer_key = "ZLzGFM9OTAR7qajKGxOIaTclA";
consumer_secret = "JHdpn58t2poNdAH5xAdaKk7T3XfQmDiL7WHtylkAaRb4kxLJgz";

# usamos auth básico
secret <- jsonlite::base64_enc(paste(consumer_key, consumer_secret, sep = ":"))
req <- httr::POST("https://api.twitter.com/oauth2/token",
  httr::add_headers(
    "Authorization" = paste("Basic", gsub("\n", "", secret)),
    "Content-Type" = "application/x-www-form-urlencoded;charset=UTF-8"
  ),
  body = "grant_type=client_credentials"
);

# extraemos el token de acceso
httr::stop_for_status(req, "authenticate with twitter")
token <- paste("Bearer", httr::content(req)$access_token)

# llamada al API
url <- "https://api.twitter.com/1.1/search/tweets.json?q=ecobici&result_type=mixed"
req <- httr::GET(url, httr::add_headers(Authorization = token))
json <- httr::content(req, as = "text")
tweets <- jsonlite::fromJSON(json)
substring(tweets$statuses$text, 1, 100)
##  [1] "Las señales con los brazos son una gran herramienta de comunicación. ¡Utilízalas! Conoce la guía cic"         
##  [2] "¿Sabes cómo inscribirte a nuestro servicio? ¡Sigue estos pasos y únete a ECOBICI! https://t.co/T6kYk"         
##  [3] "Ten presente que todo vehículo debe circular en sentido de la vialidad https://t.co/zVzCaltUzt"               
##  [4] "Si que extraño mi #Ecobici :("                                                                                
##  [5] "RT @ecobici: Las señales con los brazos son una gran herramienta de comunicación. ¡Utilízalas! Conoc"         
##  [6] "RT @ecobici: No olvidamos lo que amamos #MejorEnBici https://t.co/dfd82Sjw6A"                                 
##  [7] "@molekun Hola, por motivos de mantenimiento, nuestra línea de atención es 018003262421. ¿Cómo te pod"         
##  [8] "@pawspe Hola, por el momento no contamos con proyecto de expansión, puedes solicitar el servicio en "         
##  [9] "@krn_rmz Hola, gracias por tu reporte, canalizamos la bicicleta a taller para su atención\U0001f527\U0001f6b2"
## [10] "@GSMgo Hola, ¿te encuentras bien? ¿Puedes indicarnos tu número de tarjeta Ecobici?"                           
## [11] "@ecobici su línea telefónica no sirve y tengo un problema con una cicloestacion"                              
## [12] "@ecobici"                                                                                                     
## [13] "@mak_21 @Vbike_mx Yo \"odio\" más a @Vbike_mx por no hacer algo al respecto, al final como ya pagamos,"       
## [14] "@Meelissaae Hola, te pedimos intentar nuevamente o bien acudir a alguno de nuestros módulos de atenc"         
## [15] "RT @pasotti_: Con @ecobici, 22% deja de usar su automóvil.\nhttps://t.co/0nrBRyODgt https://t.co/oCdq"